﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace wpfTool
{
    public struct PortInfo
    {
        public string portName;
        public Type type;

        PortInfo(string name, Type valueType)
        {
            portName = name;
            type = valueType;
        }
    }

    public struct PropertyInfo
    {
        PropertyInfo(string name, System.Windows.FrameworkElement fe)
        {
            propertyName = name;
            element = fe;
        }

        public string propertyName;
        public System.Windows.FrameworkElement element;
    }

    public abstract class ShaderBase : IComparable
    {
        static int numOfInstancesCreated = 0;
        int id;

        protected string shaderName;
        protected PortInfo[] inputPortsList;
        protected PortInfo[] outputPortsList;
        protected PropertyInfo[] propertyGridItems;
        protected SortedDictionary<string, object> properyList = null;

        protected SortedDictionary<int, object> inputObjectDict = null;
        protected SortedDictionary<int, bool> inputObjectMarkDict = null;
        protected SortedDictionary<int, object> outputObjectDict = null;

        public bool usePreviewBitmap = true;

        protected ShaderBase()
        {
            id = numOfInstancesCreated++;
            shaderName = "N/A";

            properyList = new SortedDictionary<string, object>();
            inputObjectDict = new SortedDictionary<int, object>();
            inputObjectMarkDict = new SortedDictionary<int, bool>();
            outputObjectDict = new SortedDictionary<int, object>();
        }

        /// <summary>
        /// After setup the inputPortsList and
        /// outputPortsList, the inherited class 
        /// can invoke this method to simplify the 
        /// initialization process of other data member
        /// </summary>
        protected void init()
        {
            if(inputPortsList != null)
                for (int i = 0; i < inputPortsList.Length; ++i)
                {
                    inputObjectDict[i] = null;
                    inputObjectMarkDict[i] = false;
                }

            if(outputPortsList != null)
                for (int i = 0; i < outputPortsList.Length; ++i)
                {
                    outputObjectDict[i] = null;
                }

            if (PropertyItemsList == null)
                propertyGridItems = new PropertyInfo[0];
        }


        public SortedDictionary<int, object> InputObjects
        {
            get { return inputObjectDict; }
        }
        public SortedDictionary<int, bool> InputObjectMarks
        {
            get { return inputObjectMarkDict; }
        }
        public bool ReadyToUpdate
        {
            get
            {
                foreach(int index in inputObjectMarkDict.Keys)
                {
                    if (inputObjectMarkDict[index] == false)
                        return false;
                }
                return true;
            }
        }
        public SortedDictionary<int, object> OutputObjects
        {
            get { return outputObjectDict; }
        }

        //public void registerShaderManager(ShaderManager mgr)
        //{
        //    //shaderManager = mgr;
        //}

        //public void registerShaderWidget(ShaderWidget widget)
        //{
        //    this.ShaderUpdated += widget.updatePreview;
        //    this.ShaderProgressEvent += widget.updateProgressBar;
        //}

        public string ShaderName
        {
            get { return shaderName; }
        }

        public Array InputPortsList
        {
            get { return inputPortsList; }
        }

        public bool IsSrc
        {
            get { return inputPortsList == null || inputPortsList.Length == 0; }
        }

        public Array OutputPortsList
        {
            get { return outputPortsList; }
        }

        public bool IsDst
        {
            get { return outputPortsList == null || outputPortsList.Length == 0; }
        }

        public Array PropertyItemsList
        {
            get { return propertyGridItems; }
        }

        public SortedDictionary<string, object> PropertyList
        {
            get { return properyList; }
        }

        //public void onConnectionChange(int port, bool isSrc, bool isNew)
        //{
        //    this.ShaderWidgetPortHit(this, port, isSrc, isNew);
        //}

        //public void addConnection(int srcPort, int dstPort, ShaderBase dst)
        //{
        //    this.PipelineStructureChange(this, srcPort, dst, dstPort);
        //}

        //public void removeConnection(int srcPort, int dstPort, ShaderBase dst)
        //{
        //    this.PipelineStructureChange(this, srcPort, dst, dstPort);
        //}

        public void onPropertyChange(string propertyName, object value)
        {
            this.properyList[propertyName] = value;
            //this.ShaderPropertyChange(this, propertyName, value);
        }

        public void techniqueProcess() 
        { 
            technique();

            for (int index = 0; index < inputObjectMarkDict.Count; ++index)
                inputObjectMarkDict[index] = false;
        }

        protected void sendShaderUpdatedEvent(System.Drawing.Bitmap bmp)
        {
            this.ShaderUpdated(bmp);
        }

        protected void sendShaderProgressEvent(float percentage)
        {
            this.ShaderProgressEvent(percentage);
        }

        protected abstract void technique();

        public event Window1.ShaderUpdatedHandler ShaderUpdated;
        public event Window1.ShaderProgressEventHandler ShaderProgressEvent;


        int IComparable.CompareTo(object obj)
        {
            return (obj as ShaderBase).id.CompareTo(id);
        }
    }
}
